/*
* 类 + 存取器 + 静态属性
* */
/* 高级技巧 */
/*类可以做接口使用，但是不建议*/
interface Point {
    x: number,
    y: number
}
interface Point3d extends Point{
    z: number
}
let point3d:Point3d = {x: 1, y: 2, z:3};



class Greeter1 {
    static standarGreeting = 'Hello, there';
    greeting: string;
    constructor(message?:string) {
        this.greeting = message;
    }
    greet() {
        return `Hello, ${this.greeting}`;
    }
}
let greeter:Greeter1;
greeter = new Greeter1('word');
console.log(greeter.greet());

//重新创建一个
let greeterMaker: typeof Greeter1 = Greeter1;
greeterMaker.standarGreeting = 'Hey there';

let greeter2:Greeter1 = new greeterMaker();
console.log(greeter2.greet());








/* 抽象类 */
abstract class Department {
    name: string;
    constructor(name: string){
        this.name = name;
    }
    printName():void {
        console.log('Department name is ' + this.name);
    }
    abstract printMeeting():void;
}
class AccountingDepartment extends Department {
    constructor(){
        super('Departmen Name Is ' + '研发部');
    }
    printMeeting(): void {
        console.log('继承了Department的派生类');
    }
    generatorReport():void {
        console.log('生成一个报告');
    }
}
let department: Department;
// department = new Department();   //这是不行的
department = new AccountingDepartment();
department.printName();
department.printMeeting();
// 但是不能department.generatorReport();   因为department已经声明了Department类型










//派生类的基本长相
abstract class AnimalabsTract {    //abstract标识这是个抽象类
    abstract makeSound(): void;     //abstract标识这是个抽象方法
    move():void {
        console.log('abstract');
    }
}











/* 静态属性 */
class Grid{
    static origin = {x: 0,y: 0};
    scale: number;
    constructor(scale: number) {
        this.scale = scale;
    }
    caculateDistanceFromOrigin(point: {x: number, y: number}) {
        let xDist = point.x - Grid.origin.x;
        let yDist = point.y - Grid.origin.y;
        return Math.sqrt(xDist*xDist + yDist*yDist) * this.scale;
    }
}
let grid1 = new Grid(1.0);
let grid2 = new Grid(5.0);
console.log(grid1.caculateDistanceFromOrigin({x:3,y:4}));
console.log(grid2.caculateDistanceFromOrigin({x:3,y:4}));









/* 存取器 */
let passcode = 'hardy';
class Employee2 {
    private _fullName: string;
    get fullName(): string {
        return this._fullName;
    }
    set fullName(fullname: string) {
        if(fullname && fullname==='hardy'){
            this._fullName = 'hardy 正确';
        }else{
            console.log('printf:' + fullname);
        }
    }
}
let employee2 = new Employee2();
employee2.fullName = '小方块';
if(employee2.fullName && employee2.fullName === 'hardy'){
    console.log(employee2.fullName,':+++')
}











/**
 * 类 + 公共/私有 + 受保护符
 *
 public: Java语言中访问限制最宽的修饰符，一般称之为“公共的”。被其修饰的类、属性以及方法不
 　　　　　                仅可以跨类访问，而且允许跨包（package）访问。
 private: Java语言中对访问权限限制的最窄的修饰符，一般称之为“私有的”。被其修饰的类、属性以
 　　　　　               及方法只能被该类的对象访问，其子类不能访问，更不能允许跨包访问。
 protect: 介于public 和 private 之间的一种访问修饰符，一般称之为“保护形”。被其修饰的类、
 　　　　　属性以及方法只能被类本身的方法及子类访问，即使子类在不同的包中也可以访问。
 * 成员默认为public
 * */
class Person2 {
    constructor(readonly name:string){}    //不建议这么写
}
let person1 = new Person2('小方块');
console.log(person1.name);


/*readyonly*/
class Person1{
    readonly name:string;     //person.name = '小方块';报错
    constructor(name:string){
        this.name = name;
    }
}
let person = new Person1('Hardy');
person.name = '小方块';
console.log(person.name);



/*protected*/
class Person {
    protected name:string;
    protected constructor(name:string){
        this.name = name;
    }
}
class Employee1 extends Person {
    protected department:string;
    constructor(name:string,department:string){
        super(name);
        this.department = department;
    }
    getElevatorPitch(){
        return `hello my name is ${this.name} and i work in ${this.department}`;
    }
}
let howard = new Employee1('Hardy','Development');
console.log(howard.getElevatorPitch());
// console.log(howard.name);  //但是外部访问不到里头的name

// let person = new Person('Hardy');  //报错，因为person的constructor是protected










/*private*/
class Animal1 {
    private name: string;   // new Animal1('Hardy').name;  //访问不到
    constructor(name:string){
        this.name = name;
    }
    move(distance:number = 5){
        console.log(`${this.name} is moved to ${distance}`);
    }
}
class Rhino extends Animal1 {
    constructor(name:string){
        super(name);
    }
}
class Employee {
    private name:string;
    constructor(name:string){
        this.name = name;
    }
}
let animal = new Animal1('HardyAnimal');
let rhino = new Rhino('HardyRhino');
let employee = new Employee('HardyEmployee');
// animal = rhino;       //可以
// animal = employee;    //报错










/**
 * 类 + 基本示例 + 继承
 * */
class Animal {
    name:string;
    constructor(name:string){
        this.name = name;
    }
    move(distance:number = 0){
        console.log(`${this.name} moved to ${distance}`);
    }
}
class Dog extends Animal {
    tick(){
        console.log('woof woof!!')
    }
}
class Horse extends Animal {
    constructor(name:string){
        super(name);
    }
    move(distance:number = 100){
        super.move(distance);
    }
}
let horse:Animal = new Horse('Hardy');
horse.move(1000);

let dog = new Dog('小白');
dog.tick();
dog.move(20);




class Greeter {
    greeting:string
    constructor(message:string){
        this.greeting = message;
    }
    greet(){
        return `hello ${this.greeting}`;
    }
}
let greet = new Greeter('hardy');
console.log(greet.greet());